package gripper.ftp.handle;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.Callable;

import gripper.ftp.DataSocket;
import gripper.ftp.FtpSession;
import gripper.ftp.PathConvert;

public class APPEHandle implements Handle {
	FtpSession ftpSession;

	public APPEHandle(FtpSession ftpSession) {
		this.ftpSession = ftpSession;
	}

	public void process(String line, BufferedReader br, final OutputStream os) throws IOException {
		os.write("150 Opening BINARY mode data connection\r\n".getBytes());
		os.flush();
		final DataSocket sock = ftpSession.getClientSock();
		final String[] splited = line.split(" ");
		if (splited == null || splited.length < 2) {
			sock.close();
			os.write("226 Transfer complete.\r\n".getBytes());
			os.flush();
			return;
		}
		ftpSession.submit(new Callable<String>() {
			@Override
			public String call() throws Exception {
				String fileName = splited[1].trim();
				fileName = ftpSession.currentDir + "/" + fileName;
				fileName = PathConvert.toServerPath(ftpSession.getRootDir(), fileName);
				File file = new File(fileName);
				if (!file.exists()) {
					boolean success = file.createNewFile();
					if (!success) {
						sock.close();
						os.write("553 Requested action not taken.\r\n".getBytes());
						os.flush();
						return null;
					}
				}
				InputStream is = sock.getInputStream();
				try (FileOutputStream fileOut = new FileOutputStream(file, true);) {
					byte[] buf = new byte[4096];
					while (!ftpSession.abort.get()) {
						int len = is.read(buf);
						if (len < 0) {
							break;
						}
						fileOut.write(buf, 0, len);
					}
				} catch (Exception e) {
					sock.close();
					os.write("553 Requested action not taken.\r\n".getBytes());
					os.flush();
					return null;
				}
				os.write("226 Closing data connection,file transfer successful.\r\n".getBytes());
				is.close();
				sock.close();
				os.flush();
				ftpSession.abort.set(false);
				return null;
			}

		});
	}
}
